
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Spring学习指南 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>Spring学习指南 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">Spring框架的核心思想是什么？其主要目的是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Spring的核心思想是IOC（控制反转）和AOP（面向切面编程）。其主要目的是为简化企业级开发而生，通过将Bean对象、Dao组件、Service组件等交给Spring容器来管理，从而有效降低代码的耦合度，方便项目的后期维护、升级和扩展。</div>
          </div>
          <div class="card-source">来源: Spring概述 -> 简介</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">什么是控制反转（IOC）？它解决了什么核心问题？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">控制反转（IOC）是指将对象的创建权由程序员在代码中手动控制（如使用new关键字）转变为交给Spring容器来创建和管理。它解决了具有依赖关系的组件之间的强耦合问题，使得项目形态更加稳健。</div>
          </div>
          <div class="card-source">来源: IOC控制反转</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">Spring中的Bean有哪三种主要的实例化方式？最常用的是哪一种？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Spring中Bean有三种主要的实例化方式：1. 使用无参构造器；2. 使用静态工厂方法；3. 使用非静态工厂（实例工厂）方法。其中，第一种“使用无参构造”的方式是使用最多的。</div>
          </div>
          <div class="card-source">来源: IOC控制反转 -> Bean的三种实例化方式</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">Spring支持的五种Bean作用域是什么？默认的作用域是哪一个？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Spring支持五种Bean作用域：1. singleton：单例模式；2. prototype：原型模式；3. request：每次HTTP请求一个新实例；4. session：每个HTTP Session一个新实例；5. globalsession：集群环境下的全局session。如果不指定，Spring默认使用singleton作用域。</div>
          </div>
          <div class="card-source">来源: IOC控制反转 -> Spring Bean作用域</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">请解释单例（singleton）和多例（prototype）Bean在生命周期管理上的主要区别。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">单例（singleton）对象的生命周期与Spring容器直接相关：容器创建时它被创建和初始化，容器关闭后它被销毁。而多例（prototype）对象的生命周期与对象的使用有关：当对象被使用时才会被创建和初始化，当对象长时间不用且没有其他对象引用时，由Java的垃圾回收器回收，其销毁过程与容器是否关闭无关。</div>
          </div>
          <div class="card-source">来源: IOC控制反转 -> SpringBean生命周期 -> 总结</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">什么是依赖注入（DI）？它和IOC是什么关系？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">依赖注入（Dependency Injection, DI）是Spring框架核心IOC的具体实现。它指的是程序中对象之间的依赖关系由Spring容器来维护和注入，而不是由对象自身创建或查找其依赖。简单来说，就是Spring框架把一个对象（如UserDao）所依赖的另一个对象（如DataSource）传入，而不需要我们自己在代码中去获取。</div>
          </div>
          <div class="card-source">来源: DI依赖注入</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">注解</div>
          <div class="card-question">在Spring中，用于创建Bean的`@Component`、`@Service`、`@Repository`和`@Controller`注解有何异同？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">注解</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">相同点是，这四个注解的作用都是将当前类实例化为Bean对象并添加到Spring容器中。不同点在于使用场景和语义，目的是为了让三层架构更加清晰：`@Controller`用于控制层，`@Service`用于业务层，`@Repository`用于数据层（持久层），而`@Component`是通用的组件注解，用于非三层的类。</div>
          </div>
          <div class="card-source">来源: Spring注解 -> Bean创建</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">什么是面向切面编程（AOP）？它的主要应用场景有哪些？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">AOP（Aspect Orient Programming）即面向切面编程，是一种编程思想，作为面向对象编程（OOP）的补充。它利用“横切”技术，将影响多个类的公共行为封装到可重用的“切面”模块中，以降低耦合度。主要应用场景包括：日志记录、权限控制、事务控制和性能监测。</div>
          </div>
          <div class="card-source">来源: AOP思想 -> AOP概念 / AOP的使用场景</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">Spring AOP中的通知（Advice）有哪几种类型？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Spring AOP支持五种通知类型：1. `before` (前置通知)：在目标方法执行之前调用。2. `after` (后置通知)：在目标方法执行之后调用，无论是否出现异常都会执行。3. `after-returning` (返回后通知)：在目标方法成功返回值后执行，若出现异常则不执行。4. `after-throwing` (异常通知)：在目标方法抛出异常后执行。5. `around` (环绕通知)：包裹目标方法，在方法调用前后均可执行自定义逻辑。</div>
          </div>
          <div class="card-source">来源: SpringAOP -> SpringAOP通知类型 -> 总结</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">JDK动态代理和Cglib动态代理有什么核心区别？Spring在AOP中是如何选择的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">核心区别在于：JDK动态代理基于接口实现，代理类和目标类实现相同的接口，因此目标类必须有接口。Cglib动态代理基于继承实现，代理类是目标类的子类，因此不能代理被final修饰的类。Spring AOP默认情况下，如果目标对象实现了接口，就使用JDK动态代理；如果目标对象没有接口，就使用Cglib动态代理。</div>
          </div>
          <div class="card-source">来源: 代理设计模式 -> Cglib和Jdk动态代理的对比 & SpringAOP -> SpringAOP代理的选择</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">Spring提供了哪两种事务管理方式？更推荐使用哪一种，为什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Spring提供了两种事务管理方式：编程式事务和声明式事务。Spring推荐使用声明式事务处理，因为它能让开发者从繁琐的事务管理代码中解脱出来，无需在业务代码中编写事务控制逻辑，只需通过XML配置或注解就可以为普通Java类添加事务管理，其底层是利用AOP思想实现的。</div>
          </div>
          <div class="card-source">来源: Spring控制事务</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">注解</div>
          <div class="card-question">`@Autowired`和`@Qualifier`注解如何协同工作以解决依赖注入时的歧义性问题？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">注解</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`@Autowired`默认是按照类型进行自动注入的。如果IOC容器中存在多个与所需类型匹配的Bean，注入就会失败。这时，可以配合使用`@Qualifier`注解，通过在其`value`属性中指定目标Bean的ID，来明确告诉Spring容器应该注入哪一个Bean，从而解决歧义性问题。</div>
          </div>
          <div class="card-source">来源: Spring注解 -> 依赖注入</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
